home *** CD-ROM | disk | FTP | other *** search
- PROGRAM SpaceInv;
-
- USES CRT, DOS;
-
- {
- VERSION 5.2 -- By Timothy Campbell
- ══════════════════════════════════
- It ain't much, but it does work!
- }
-
-
- TYPE
- Line = STRING[80];
- Sprite = STRING[7];
- SpriteType = (Base,Missle,Ufo1,Bomb1,Ufo2,Bomb2,Ufo3,Bomb3,Ufo4,Bomb4,
- Ufo5,Bomb5,Ufo6,Bomb6);
- Switch = (Off,On);
-
-
- CONST
- Blanks = ' ';
- DelayAdj = 3;
- DelayInit = 70;
- NumSyms = 13;
- Shields = ' '#176#177#178#219;
- Sprites : ARRAY [0..NumSyms] OF Sprite =
- ( #213#209#202#209#184,
- #024,
- #017#016#174#153#175#017#016,
- #079,
- #060#243#234#242#062,
- #147,
- #174#017#016#175,
- #015,
- #017#001#016,
- #157,
- #199#002#182,
- #031,
- #233,
- 'v' );
- Explode : ARRAY [0..5] OF Sprite =
- ( #219#219#219#219#219#219#219,
- #178#178#178#178#178#178#178,
- #177#177#177#177#177#177#177,
- #176#176#176#176#176#176#176,
- '- - - - -',
- ' ' );
-
- VAR
- Active : ARRAY[0..NumSyms] OF BOOLEAN;
- ActiveCnt : BYTE;
- Beat : INTEGER;
- BombType : SpriteType;
- DelayTime : INTEGER;
- Explosion : BYTE;
- InChar : CHAR;
- MisX : BYTE;
- MisY : BYTE;
- Move : ARRAY[0..NumSyms] OF INTEGER;
- MoveUfo6 : BYTE;
- Noise : BOOLEAN;
- NowX : BYTE;
- NowY : BYTE;
- ShieldLev : BYTE;
- RandomMod : BYTE;
- Score : INTEGER;
- ShieldCnt : INTEGER;
- SpriteLen : BYTE;
- SprX : BYTE;
- SprY : BYTE;
- Thingy : INTEGER;
- Tick : BYTE;
- UfoTick : BYTE;
- UfoType : SpriteType;
- WX,WY : BYTE;
- XPosn : ARRAY[0..NumSyms] OF BYTE;
- YPosn : ARRAY[0..NumSyms] OF BYTE;
-
- FUNCTION Divis(Dv1,Dv2 : INTEGER) : BOOLEAN;
- BEGIN
- IF (Dv1 DIV Dv2) * Dv2 = Dv1
- THEN Divis := TRUE
- ELSE Divis := FALSE;
- END;
-
- PROCEDURE Ce(CIn : Line);
- BEGIN
- GOTOXY(((80 - LENGTH(Cin)) DIV 2),WHEREY);
- WRITELN(CIn);
- END;
-
- FUNCTION Sz(SIn : Line) : Line;
- BEGIN
- Sz := Copy((SIn + Blanks),1,7);
- END;
-
- PROCEDURE DawdleJet;
- VAR
- BanLoop : BYTE;
- Mult : INTEGER;
- BEGIN
- Mult := 1;
- Thingy := 100;
- REPEAT
- Thingy := Thingy + Mult;
- IF Thingy > 4000 THEN Mult := -1;
- IF Thingy < 100 THEN Mult := 1;
- FOR BanLoop := 1 TO 5 DO
- BEGIN
- SOUND(Thingy);
- DELAY(1);
- SOUND(4200-Thingy);
- DELAY(1+RANDOM(8));
- END;
- UNTIL KEYPRESSED;
- InChar := READKEY;
- NOSOUND;
- END;
-
- PROCEDURE DawdleNoise;
- BEGIN
- REPEAT
- SOUND(200+RANDOM(3000));
- DELAY(1+RANDOM(8));
- NOSOUND;
- DELAY(1+RANDOM(50));
- UNTIL KEYPRESSED;
- InChar := READKEY;
- NOSOUND;
- END;
-
- PROCEDURE Banner;
- BEGIN
- CLRSCR;
- Ce('┌───────────────────────────────────────────────────────┬──────────────────┐');
- Ce('│ Pinnacle Software''s Space Investors Video Game │ SPACEINV │');
- Ce('├───────────────────────────────────────────────────────┴──────────────────┤');
- Ce('│ C O P Y R I G H T (C) 1989 BY P I N N A C L E S O F T W A R E │');
- Ce('├──────────────────────────────────────────────────────────────────────────┤');
- Ce('│ This program may be freely distributed so long as it is distributed in │');
- Ce('│ its complete and unaltered form, including this notice. │');
- Ce('├──────────────────────────────────────────────────────────────────────────┤');
- Ce('├─────────────── ╦══╗ ═╦═ ╦═╗ ╔ ╦═╗ ╔ ╔══╗ ╔══╗ ╦ ╦══╗ ───────────────┤');
- Ce('├─────────────── ╠══╝ ║ ║ ║ ║ ║ ║ ║ ╠══╣ ║ ║ ╠═ ───────────────┤');
- Ce('├─ ── ╩ ═╩═ ╝ ╚═╝ ╝ ╚═╝ ╩ ╩ ╚══╝ ╩══╝ ╩══╝ ── ─┤');
- Ce('├ VOICE LINE ─ ╔══╗ ╔══╗ ╦══╗ ╔═╦═╗ ╗ ╔ ╔═╗ ╦══╗ ╦══╗ ─ DATA LINE ┤');
- Ce('├ 514-345-9578 ─ ╚══╗ ║ ║ ╠═ ║ ║ ║ ║ ╠═╣ ╠═╦╝ ╠═ ─ 514-345-8654 ┤');
- Ce('├─ ── ╚══╝ ╚══╝ ╩ ╩ ╚═╩═╝ ╩ ╩ ╩ ╚╝ ╩══╝ ── ─┤');
- Ce('├─────────────── Post Office Box 386, Town of Mount Royal ───────────────┤');
- Ce('├─────────────── Cartierville, Quebec, Canada, H3P 3C6 ───────────────┤');
- Ce('└──────────────────────────────────────────────────────────────────────────┘');
- WRITELN;
- Ce('PRESS A KEY TO CONTINUE');
- DawdleJet;
- CLRSCR;
- Ce('PINNACLE SOFTWARE PRESENTS');
- Ce('┌─-─=─=─=─=─=─=─=─=─=─=─=─=─=─=─=─-─┐');
- Ce(') S P A C E I N V E S T O R S (');
- Ce('└─-─=─=─=─=─=─=─=─=─=─=─=─=─=─=─=─-─┘');
- WRITELN;
- Ce('Watch out for ...');
- WRITELN;
- Ce('THE MOTHER SHIP ' + Sz(Sprites[ORD(Ufo1)]));
- Ce('THE BATTLE POD ' + Sz(' '+Sprites[ORD(Ufo2)]));
- Ce('THE DRIFTER ' + Sz(' '+Sprites[ORD(Ufo3)]));
- Ce('THE HARASSER ' + Sz(' '+Sprites[ORD(Ufo4)]));
- Ce('THE DARE-DEVIL ' + Sz(' '+Sprites[ORD(Ufo5)]));
- Ce('THE OBSERVER ' + Sz(' '+Sprites[ORD(Ufo6)]));
- WRITELN;
- Ce(' The keys are used as follows... ');
- Ce(' F and J ..... move base left and right ');
- Ce(' E and I ..... either key will stop base movement');
- Ce(' Spacebar .... fires a missle ');
- Ce(' - (minus) ... toggles sound on and off ');
- Ce(' P ........... pauses the game ');
- Ce(' ESC ......... exits the game (you coward!) ');
- WRITELN;
- Ce('*** PRESS A KEY TO START ***');
- DawdleNoise;
- END;
-
- PROCEDURE ShowScore;
- BEGIN
- GOTOXY(1,25);
- WRITE('SCORE: ',Score,' SHIELD LEVEL: ',
- Copy(Shields,1,ShieldLev),' ');
- END;
-
- PROCEDURE Cursor(CCtl : Switch);
- TYPE
- regpack =
- RECORD
- ax,bx,cx,dx,bp,di,si,ds,es,flags: INTEGER;
- END;
- VAR
- recpack : REGISTERS;
- BEGIN
- WITH recpack DO
- BEGIN
- ax := $0100;
- IF CCtl = On
- THEN cx := $0CCD { 12, 13 }
- ELSE cx := $FFFF;
- END;
- INTR($10,recpack);
- END;
-
- PROCEDURE BEEP(Tone : INTEGER);
- BEGIN
- IF Noise THEN SOUND(Tone);
- END;
-
- PROCEDURE SetPosn(IntST : SpriteType; IntX, IntY : BYTE);
- BEGIN
- IF ((IntX = 0) AND (IntY = 0)) AND (Active[ORD(IntST)] = TRUE) THEN
- BEGIN
- Active[ORD(IntST)] := FALSE;
- ActiveCnt := ActiveCnt - 1;
- END;
- IF ((IntX > 0) AND (IntY > 0)) THEN
- BEGIN
- IF Active[ORD(IntST)] = FALSE THEN
- BEGIN
- Active[ORD(IntST)] := TRUE;
- IF (RANDOM(100) < 33) AND (IntST IN [Ufo1,Ufo2,Ufo3,Ufo4,Ufo5,Ufo6]) THEN
- BEGIN
- Move[ORD(IntST)] := -1;
- IntX := 80 - LENGTH(Sprites[ORD(IntST)]) - 1;
- END
- ELSE Move[ORD(IntST)] := 1;
- ActiveCnt := ActiveCnt + 1;
- END;
- XPosn[ORD(IntST)] := IntX;
- YPosn[ORD(IntST)] := IntY;
- END;
- END;
-
- PROCEDURE FindXY(FndST : SpriteType);
- BEGIN
- NowX := XPosn[ORD(FndST)];
- NowY := YPosn[ORD(FndST)];
- END;
-
- {======= MOVEMENT =======}
-
- PROCEDURE MoveX(SprTyp : SpriteType);
- VAR
- OutSprite : STRING[9];
- XGo : BYTE;
- YGo : BYTE;
- BEGIN
- OutSprite := Sprites[ORD(SprTyp)];
- SpriteLen := Length(OutSprite);
- FindXY(SprTyp);
- IF SprTyp <> Base THEN
- BEGIN
- IF (RANDOM(1000) < SpriteLen * 5)
- OR ((SprTyp = Ufo6) AND (RANDOM(100) < 5)) THEN
- BEGIN
- IF NowX < XPosn[ORD(Base)] THEN Move[ORD(SprTyp)] := 1;
- IF NowX > XPosn[ORD(Base)] THEN Move[ORD(SprTyp)] := -1;
- END;
- END;
- XGo := NowX + Move[ORD(SprTyp)];
- IF XGo < 1 THEN XGo := 1;
- IF XGo + SpriteLen > 80 THEN XGo := 80 - SpriteLen;
- SetPosn(SprTyp,XGo,NowY);
- IF SprTyp <> Base THEN
- BEGIN
- IF RANDOM(120) < ORD(SprTyp) THEN
- BEGIN
- OutSprite := COPY(Blanks,1,SpriteLen);
- IF RANDOM(100) < 33
- THEN YGo := NowY - 1
- ELSE YGo := NowY + 1;
- IF YGo < 1 THEN YGo := 1;
- IF YGo > 18 THEN YGo := 17;
- GOTOXY(NowX,YGo);
- WRITE(Sprites[ORD(SprTyp)]);
- FOR Thingy := 40 DOWNTO 5 DO BEEP(Thingy * 100);
- SetPosn(SprTyp,NowX,YGo);
- END;
- END;
- IF (XGo > 1) AND (Move[ORD(SprTyp)] > 0) THEN
- BEGIN
- XGo := XGo - 1;
- OutSprite := ' ' + OutSprite;
- END;
- IF (XGo < 80) AND (Move[ORD(SprTyp)] < 0) THEN OutSprite := OutSprite + ' ';
- GOTOXY(XGo,NowY);
- WRITE(OutSprite);
- END;
-
- PROCEDURE CheckBoom(BWep, Wnme : SpriteType; MisX, MisY : BYTE);
- BEGIN
- FindXY(Wnme);
- SpriteLen := LENGTH(Sprites[ORD(Wnme)]);
- IF (MisX IN [NowX .. (NowX + SpriteLen-1)]) AND (MisY = NowY)
- AND Active[ORD(Wnme)]
- THEN
- BEGIN
- FOR Explosion := 0 TO 5 DO
- BEGIN
- FOR Thingy := 1 TO (SpriteLen * 10) DO
- BEGIN
- DELAY(1);
- BEEP(500+RANDOM(4000 - Thingy * 50));
- END;
- GOTOXY(NowX,NowY);
- WRITE(Copy(Explode[Explosion],1,SpriteLen));
- END;
- IF BWep = Missle THEN
- BEGIN
- Score := Score + (14 - ORD(Wnme)) * 10;
- SetPosn(Wnme,0,0);
- SetPosn(Missle,0,0);
- END
- ELSE
- BEGIN
- IF Divis(Beat,3)
- THEN Move[ORD(PRED(BWep))] := Move[ORD(PRED(Bwep))] * -1;
- Score := Score - 100;
- IF Score < 0 THEN Score := 0;
- SetPosn(BWep,0,0);
- ShieldLev := ShieldLev - 1;
- END;
- ShowScore;
- END; { Weapon hit enemy }
- END; { CheckBoom }
-
-
- PROCEDURE MoveWeapon(WType : SpriteType);
- BEGIN
- IF Active[ORD(WType)] THEN
- BEGIN
- FindXY(WType);
- GOTOXY(NowX,NowY);
- WRITE(' ');
- IF (PRED(WType) IN [Ufo1,Ufo2]) THEN
- BEGIN
- {-- Smart Bomb --}
- IF Divis(Beat,ORD(WType)*3)
- AND Active[ORD(PRED(WType))]
- THEN
- BEGIN
- FOR Thingy := 1 TO (Score DIV 1000) DO
- BEGIN
- IF XPosn[ORD(Base)] > NowX THEN NowX := NowX + 1;
- IF XPosn[ORD(Base)] < NowX THEN NowX := NowX - 1;
- END;
- END;
- END;
- IF WType = Missle
- THEN NowY := NowY - 1
- ELSE NowY := NowY + 1;
- IF NOT (NowY IN [1..24])
- THEN SetPosn(WType,0,0)
- ELSE
- BEGIN
- BEEP(500+(ORD(WType)*RANDOM(200))+(25-NowY)*100);
- GOTOXY(NowX,NowY);
- WRITE(Sprites[ORD(WType)]);
- SetPosn(WType,NowX,NowY);
- WX := NowX;
- WY := NowY;
- IF WType = Missle
- THEN
- BEGIN
- CheckBoom(WType,Ufo1,WX,WY);
- CheckBoom(WType,Ufo2,WX,WY);
- CheckBoom(WType,Ufo3,WX,WY);
- CheckBoom(WType,Ufo4,WX,WY);
- CheckBoom(WType,Ufo5,WX,WY);
- CheckBoom(WType,Ufo6,WX,WY);
- END
- ELSE CheckBoom(WType,Base,WX,WY);
- END; { Weapon on screen }
- END; { Specified weapon active }
- END;
-
-
- PROCEDURE MoveUfo(UfoST : SpriteType);
- BEGIN
- {--- Ufo Movement ---}
- IF Active[ORD(UfoST)] THEN
- BEGIN
- IF (Tick IN [1..7]) THEN Move[ORD(UfoST)] := Move[ORD(UfoST)] * -1;
- UfoTick := UfoTick + RANDOM(3);
- IF UfoTick > 99 THEN UfoTick := 0;
- IF Divis(UfoTick,(ORD(UfoST) DIV 2)) THEN
- BEGIN
- MoveX(UfoST);
- BEEP(ORD(UfoST) * 300);
- DELAY(1);
- SprX := NowX;
- FindXY(Base);
- {--- Drop a bomb? ---}
- IF (NOT Active[ORD(UfoST)+1]) { Not if one already dropping }
- AND
- (((Beat < LENGTH(Sprites[ORD(UfoST)])*10) AND
- (SprX IN [NowX-1,NowX,NowX+1])) { Bigger Ufo's use good shots }
- OR
- (Beat < (Score DIV 20))) { 100% chance at score 2000 }
- AND (NOT ((UfoST = Ufo6) AND (RANDOM(1000) < 995))) { Rare bomber }
- THEN
- BEGIN
- BEEP(1200);
- FindXY(UfoST);
- SetPosn(SUCC(UfoST),
- (NowX+(LENGTH(Sprites[ORD(UfoST)]) DIV 2)),
- NowY+1);
- END;
- SpriteLen := LENGTH(Sprites[ORD(UfoST)]);
- FindXY(UfoST);
- IF (NowX = 1) OR ((NowX + SpriteLen) > 79) THEN
- BEGIN
- SetPosn(UfoST,0,0);
- BEEP(3500);
- GOTOXY(NowX,NowY);
- WRITE(Copy(Blanks,1,SpriteLen));
- END;
- END; { Ufo Movement }
- END; { Ufo Introduction }
- END; { MoveUfo }
-
- {======= INITIALIZATION =======}
-
-
- PROCEDURE StartUp;
- VAR
- Loop1 : BYTE;
-
- BEGIN
- Banner;
- CLRSCR;
- ActiveCnt := 0;
- Beat := 0;
- InChar := '?';
- Noise := TRUE;
- RandomMod := 0;
- Score := 0;
- ShieldCnt := 0;
- ShieldLev := 5;
- UfoTick := 0;
- FOR Loop1 := 0 TO NumSyms DO
- BEGIN
- Active[Loop1] := FALSE;
- Move[Loop1] := 0;
- XPosn[Loop1] := 0;
- YPosn[Loop1] := 0;
- END;
- SetPosn(Base,39,24);
- END;
-
-
- {======= MAINLINE =======}
-
-
- BEGIN
- StartUp;
- Cursor(Off);
- ShowScore;
- REPEAT
- IF (Score DIV 1000 > ShieldCnt) AND (ShieldLev < 5)
- THEN
- BEGIN
- ShieldLev := ShieldLev + 1;
- ShieldCnt := ShieldCnt + 1;
- ShowScore;
- END;
- {--- Beats and Ticks ---}
- Tick := RANDOM(50) + RandomMod;
- IF InChar = 'F' THEN RandomMod := RandomMod + 1;
- IF RandomMod > 50 THEN RandomMod := 0;
- Beat := Beat + 1;
- IF Beat > 100 THEN Beat := 0;
- {--- Commands ---}
- IF KEYPRESSED THEN
- BEGIN
- BEEP(500);
- InChar := READKEY;
- InChar := UPCASE(InChar);
- CASE InChar OF
- '-' : BEGIN
- Noise := NOT Noise;
- NOSOUND;
- END;
- 'F' : Move[ORD(Base)] := -1;
- 'J' : Move[ORD(Base)] := 1;
- 'I' : Move[ORD(Base)] := 0;
- 'E' : Move[ORD(Base)] := 0;
- ' ' : BEGIN
- Score := Score - 1;
- IF Score < 0 THEN Score := 0;
- IF Active[ORD(Missle)] THEN
- BEGIN
- FindXY(Missle);
- GOTOXY(NowX,NowY);
- WRITE(' ');
- END;
- BEEP(2200);
- FindXY(Base);
- SetPosn(Missle,NowX+3,23);
- END; { SPACE CASE }
- 'P' : BEGIN
- NOSOUND;
- GOTOXY(70,1);
- WRITE('*PAUSED*');
- REPEAT UNTIL KEYPRESSED;
- InChar := READKEY;
- InChar := '?';
- GOTOXY(70,1);
- WRITE(' ');
- END;
- END; { CASE }
- END;
- {--- Timing Delay ---}
- DelayTime := DelayInit - ActiveCnt * DelayAdj;
- DelayTime := DelayTime - (Score DIV 250);
- IF DelayTime < 0 THEN DelayTime := 0;
- IF Divis(Beat,10) THEN BEEP(150);
- DELAY(DelayTime);
- {--- Base Movement ---}
- MoveX(Base);
- IF (Divis(Beat,2)) AND (Move[ORD(Base)] <> 0)
- THEN BEEP(1000+NowX*10)
- ELSE NOSOUND;
- {--- Weapon Movement ---}
- MoveWeapon(Missle);
- IF ShieldLev > 0 THEN
- BEGIN
- {--- Bring in a new UFO? ---}
- UfoType := Ufo1;
- IF Beat > 10 THEN UfoType := Ufo2;
- IF Beat > 25 THEN UfoType := Ufo3;
- IF Beat > 50 THEN UfoType := Ufo4;
- IF Beat > 75 THEN UfoType := Ufo5;
- IF Beat > 90 THEN UfoType := Ufo6;
- IF ((RANDOM(1000) <= (Score DIV 100) + 15)
- OR (ActiveCnt <= 2))
- AND (Active[ORD(UfoType)] = FALSE)
- THEN SetPosn(UfoType,1,ORD(UfoType) + RANDOM(5));
- MoveWeapon(Bomb1);
- MoveUfo(Ufo1);
- MoveWeapon(Bomb2);
- MoveUfo(Ufo2);
- MoveWeapon(Bomb3);
- MoveUfo(Ufo3);
- MoveWeapon(Bomb4);
- MoveUfo(Ufo4);
- MoveWeapon(Bomb5);
- MoveUfo(Ufo5);
- MoveWeapon(Bomb6);
- FOR MoveUfo6 := 1 to 5 DO
- BEGIN
- MoveUfo(Ufo6);
- END;
- END; { ShieldLev > 0 }
- IF ShieldLev <= 0 THEN
- BEGIN
- CLRSCR;
- WRITELN;
- WRITELN(' G A M E O V E R -- Score: ',Score);
- WRITELN;
- IF Noise THEN
- BEGIN
- FOR Thingy := 4 DOWNTO 1 DO
- BEGIN
- SOUND(500+Thingy * 1000);
- DELAY(500+RANDOM(5-Thingy)*80);
- END;
- END;
- END;
- UNTIL (InChar = #27) OR (ShieldLev = 0);
- NOSOUND;
- Cursor(On);
- END.